from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
from .models import User, ROLE_USER
from django.contrib.auth.hashers import make_password
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from django.db import DatabaseError
from django.contrib.auth import update_session_auth_hash

from django.views.decorators.csrf import ensure_csrf_cookie
# 新增：图像处理与设置
from django.conf import settings
from django.core.files.base import ContentFile
from PIL import Image, ImageOps
import io, time
from django.db.models import Q

# 登录视图
def login_view(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            messages.success(request, '登录成功！')
            return redirect('home')  # 登录成功后重定向到首页
        else:
            messages.error(request, '用户名或密码错误！')
    
    return render(request, 'users/login.html')

# 注册视图
def register_view(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        phone = request.POST.get('phone', '')
        email = request.POST.get('email', '')
        
        # 验证密码是否一致
        if password != confirm_password:
            messages.error(request, '两次输入的密码不一致！')
            return render(request, 'users/register.html')
        
        # 检查用户名是否已存在
        if User.objects.filter(username=username).exists():
            messages.error(request, '用户名已存在！')
            return render(request, 'users/register.html')
        
        # 检查手机号格式（如果提供）
        if phone and (len(phone) != 11 or not phone.isdigit()):
            messages.error(request, '请输入有效的手机号码！')
            return render(request, 'users/register.html')
        
        # 创建新用户（默认角色为普通用户），密码将自动加密存储
        user = User.objects.create_user(
            username=username,
            password=password,
            phone=phone,
            email=email or None,
            role=ROLE_USER
        )
        
        # 无缝对接登录：注册完成后自动登录
        user_authenticated = authenticate(request, username=username, password=password)
        if user_authenticated is not None:
            login(request, user_authenticated)
            messages.success(request, '注册成功，已自动登录！')
            return redirect('home')
        else:
            messages.success(request, '注册成功，请登录！')
            return redirect('login')
    
    return render(request, 'users/register.html')

# 退出登录视图
def logout_view(request):
    logout(request)
    messages.success(request, '已成功退出登录！')
    return redirect('login')

# 首页视图
def home_view(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    # 根据用户角色显示不同的内容
    role_name = request.user.get_role_display()
    
    context = {
        'user': request.user,
        'role_name': role_name
    }
    
    return render(request, 'users/home.html', context)

@ensure_csrf_cookie
# 片段版个人用户信息视图
def profile_fragment_view(request):
    if not request.user.is_authenticated:
        return redirect('login')
    role_name = request.user.get_role_display()
    context = {
        'user': request.user,
        'role_name': role_name,
        'avatar_size': getattr(settings, 'AVATAR_SIZE', 256)
    }
    return render(request, 'users/profile.html', context)

# 个人用户信息页面视图
def profile_view(request):
    if not request.user.is_authenticated:
        return redirect('login')
    # 获取用户角色名称
    role_name = request.user.get_role_display()
    context = {
        'user': request.user,
        'role_name': role_name
    }
    return render(request, 'users/profile.html', context)

# API登录（支持AJAX调用）
@csrf_exempt
def api_login(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            username = data.get('username')
            password = data.get('password')
            
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                return JsonResponse({
                    'status': 'success',
                    'message': '登录成功',
                    'role': user.role,
                    'username': user.username
                })
            else:
                return JsonResponse({
                    'status': 'error',
                    'message': '用户名或密码错误'
                }, status=401)
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': f'登录失败: {str(e)}'
            }, status=500)
    
    return JsonResponse({
        'status': 'error',
        'message': '方法不允许'
    }, status=405)

@login_required
@require_POST
def profile_update(request):
    try:
        if request.content_type == 'application/json':
            payload = json.loads(request.body or '{}')
        else:
            payload = request.POST.dict()
        user = request.user
        # 更新邮箱
        if 'email' in payload:
            email = (payload.get('email') or '').strip()
            if email:
                try:
                    validate_email(email)
                except ValidationError:
                    return JsonResponse({'status': 'error', 'message': '邮箱格式不正确'}, status=400)
                user.email = email
            else:
                user.email = ''
        # 更新手机号
        if 'phone' in payload:
            phone = (payload.get('phone') or '').strip()
            if phone:
                if not phone.isdigit() or len(phone) != 11:
                    return JsonResponse({'status': 'error', 'message': '请输入11位手机号码'}, status=400)
                user.phone = phone
            else:
                user.phone = ''
        # 可选：更新用户名
        if 'username' in payload:
            username = (payload.get('username') or '').strip()
            if not username:
                return JsonResponse({'status': 'error', 'message': '用户名不能为空'}, status=400)
            if username != user.username and User.objects.filter(username=username).exists():
                return JsonResponse({'status': 'error', 'message': '用户名已存在'}, status=409)
            user.username = username
        # 新增：更新性别
        if 'gender' in payload:
            gender = (payload.get('gender') or '').strip()
            if gender and gender not in ('male', 'female'):
                return JsonResponse({'status': 'error', 'message': '性别取值不合法'}, status=400)
            user.gender = (gender or None)
        user.save()
        role_name = user.get_role_display()
        gender_map = {'male': '男', 'female': '女'}
        return JsonResponse({
            'status': 'success',
            'message': '保存成功',
            'data': {
                'id': user.id,
                'username': user.username,
                'email': user.email or '',
                'phone': user.phone or '',
                'role': user.role,
                'role_name': role_name,
                'gender': (user.gender or ''),
                'gender_name': gender_map.get(user.gender or '', ''),
                'is_active': user.is_active,
                'date_joined': user.date_joined.strftime('%Y-%m-%d %H:%M:%S'),
                'last_login': user.last_login.strftime('%Y-%m-%d %H:%M:%S') if user.last_login else '',
                'avatar_url': (user.avatar.url if user.avatar else '')
            }
        })
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'保存失败: {str(e)}'}, status=500)

@login_required
def profile_data(request):
    try:
        user = request.user
        role_name = user.get_role_display()
        gender_map = {'male': '男', 'female': '女'}
        return JsonResponse({
            'status': 'success',
            'data': {
                'id': user.id,
                'username': user.username,
                'email': user.email or '',
                'phone': user.phone or '',
                'role': user.role,
                'role_name': role_name,
                'gender': (user.gender or ''),
                'gender_name': gender_map.get(user.gender or '', ''),
                'is_active': user.is_active,
                'date_joined': user.date_joined.strftime('%Y-%m-%d %H:%M:%S'),
                'last_login': user.last_login.strftime('%Y-%m-%d %H:%M:%S') if user.last_login else '',
                'avatar_url': (user.avatar.url if user.avatar else '')
            }
        })
    except DatabaseError:
        return JsonResponse({'status': 'error', 'message': '数据库连接异常，请稍后重试'}, status=500)
    except Exception:
        return JsonResponse({'status': 'error', 'message': '系统异常，请稍后重试'}, status=500)


@login_required
@require_POST
def profile_avatar_upload(request):
    try:
        file = request.FILES.get('avatar')
        if not file:
            return JsonResponse({'status': 'error', 'message': '未选择文件'}, status=400)
        # 校验文件类型（仅允许 JPG/PNG）
        content_type = (file.content_type or '').lower()
        name_lower = (file.name or '').lower()
        allowed_types = ('image/jpeg', 'image/png')
        allowed_exts = ('.jpg', '.jpeg', '.png')
        if content_type not in allowed_types and not any(name_lower.endswith(ext) for ext in allowed_exts):
            return JsonResponse({'status': 'error', 'message': '仅支持JPG或PNG格式'}, status=400)
        # 读取并按设置尺寸裁剪/缩放为正方形
        size = getattr(settings, 'AVATAR_SIZE', 256)
        image = Image.open(file)
        # 决定输出格式：PNG保留透明，其他转为JPEG
        original_format = (image.format or '').upper()
        if original_format == 'PNG':
            image = image.convert('RGBA')
            out_format, ext = 'PNG', 'png'
        else:
            image = image.convert('RGB')
            out_format, ext = 'JPEG', 'jpg'
        # 居中裁剪并缩放到标准尺寸
        image = ImageOps.fit(image, (size, size), Image.LANCZOS, centering=(0.5, 0.5))
        # 写入内存并保存到用户头像字段
        buffer = io.BytesIO()
        save_kwargs = {'optimize': True}
        if out_format == 'JPEG':
            save_kwargs.update({'quality': 90})
        image.save(buffer, format=out_format, **save_kwargs)
        buffer.seek(0)
        filename = f"avatar_{request.user.id}_{int(time.time())}.{ext}"
        content = ContentFile(buffer.read())
        user = request.user
        user.avatar.save(filename, content, save=True)
        avatar_url = user.avatar.url if user.avatar else ''
        return JsonResponse({'status': 'success', 'message': '上传成功', 'avatar_url': avatar_url})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'上传失败: {str(e)}'}, status=500)


@login_required
@require_POST
def profile_password_change(request):
    """
    修改密码：验证当前密码 -> 校验新密码复杂度与确认一致 -> 加密保存
    返回JSON：{status: 'success'|'error', message: str}
    """
    try:
        # 读取payload，支持JSON与表单
        if request.content_type == 'application/json':
            payload = json.loads(request.body or '{}')
        else:
            payload = request.POST.dict()
        current_password = (payload.get('current_password') or '').strip()
        new_password = (payload.get('new_password') or '').strip()
        confirm_password = (payload.get('confirm_password') or '').strip()

        if not current_password or not new_password or not confirm_password:
            return JsonResponse({'status': 'error', 'message': '请完整填写当前密码与新密码'}, status=400)
        if new_password != confirm_password:
            return JsonResponse({'status': 'error', 'message': '两次输入的新密码不一致'}, status=400)

        # 已按要求删除密码复杂度校验

        user = request.user
        # 验证当前密码
        if not user.check_password(current_password):
            return JsonResponse({'status': 'error', 'message': '当前密码不正确'}, status=401)

        # 设置新密码并保持会话有效
        user.set_password(new_password)
        user.save()
        update_session_auth_hash(request, user)
        return JsonResponse({'status': 'success', 'message': '密码修改成功'})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'密码修改失败: {str(e)}'}, status=500)

# =====================
# 用户管理 CRUD 接口
# =====================

@login_required
def users_list(request):
    """获取用户列表，支持关键词搜索与分页"""
    try:
        if not (request.user.is_staff or request.user.role in ('super_admin', 'admin')):
            return JsonResponse({'status': 'error', 'message': '无权限'}, status=403)
        q = (request.GET.get('q') or '').strip()
        role = (request.GET.get('role') or '').strip()
        page = int(request.GET.get('page') or 1)
        page_size = min(int(request.GET.get('page_size') or 10), 50)
        qs = User.objects.all().order_by('-date_joined')
        if q:
            qs = qs.filter(Q(username__icontains=q) | Q(email__icontains=q) | Q(phone__icontains=q))
        if role in ('super_admin', 'admin', 'user'):
            qs = qs.filter(role=role)
        total = qs.count()
        start = (page - 1) * page_size
        end = start + page_size
        users = []
        for u in qs[start:end]:
            users.append({
                'id': u.id,
                'username': u.username,
                'email': u.email or '',
                'phone': u.phone or '',
                'role': u.role,
                'is_active': u.is_active,
                'date_joined': u.date_joined.strftime('%Y-%m-%d %H:%M:%S'),
                'avatar_url': (u.avatar.url if u.avatar else '')
            })
        return JsonResponse({
            'status': 'success',
            'data': {
                'users': users,
                'pagination': {
                    'page': page,
                    'page_size': page_size,
                    'total': total,
                    'has_next': end < total
                }
            }
        })
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'获取列表失败: {str(e)}'}, status=500)

@login_required
@require_POST
def users_create(request):
    """新增用户"""
    try:
        if not (request.user.is_staff or request.user.role in ('super_admin', 'admin')):
            return JsonResponse({'status': 'error', 'message': '无权限'}, status=403)
        payload = json.loads(request.body or '{}') if request.content_type == 'application/json' else request.POST.dict()
        username = (payload.get('username') or '').strip()
        email = (payload.get('email') or '').strip()
        phone = (payload.get('phone') or '').strip()
        role = (payload.get('role') or 'user').strip()
        password = (payload.get('password') or '123456').strip()
        if not username:
            return JsonResponse({'status': 'error', 'message': '用户名不能为空'}, status=400)
        if User.objects.filter(username=username).exists():
            return JsonResponse({'status': 'error', 'message': '用户名已存在'}, status=409)
        if email:
            try:
                validate_email(email)
            except ValidationError:
                return JsonResponse({'status': 'error', 'message': '邮箱格式不正确'}, status=400)
        if phone:
            if not phone.isdigit() or len(phone) != 11:
                return JsonResponse({'status': 'error', 'message': '请输入11位手机号码'}, status=400)
        if role not in ('super_admin', 'admin', 'user'):
            role = 'user'
        user = User.objects.create_user(
            username=username,
            email=email or None,
            password=password,
            phone=phone or None,
            role=role
        )
        return JsonResponse({'status': 'success', 'message': '新增成功', 'data': {'id': user.id}})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'新增失败: {str(e)}'}, status=500)

@login_required
@require_POST
def users_update(request, user_id: int):
    """编辑用户信息"""
    try:
        if not (request.user.is_staff or request.user.role in ('super_admin', 'admin')):
            return JsonResponse({'status': 'error', 'message': '无权限'}, status=403)
        payload = json.loads(request.body or '{}') if request.content_type == 'application/json' else request.POST.dict()
        user = User.objects.filter(pk=user_id).first()
        if not user:
            return JsonResponse({'status': 'error', 'message': '用户不存在'}, status=404)
        # 禁止普通管理员修改超级管理员
        if user.role == 'super_admin' and request.user.role != 'super_admin':
            return JsonResponse({'status': 'error', 'message': '无权修改超级管理员'}, status=403)
        username = (payload.get('username') or user.username).strip()
        email = (payload.get('email') or (user.email or '')).strip()
        phone = (payload.get('phone') or (user.phone or '')).strip()
        role = (payload.get('role') or user.role).strip()
        is_active = payload.get('is_active')
        password = (payload.get('password') or '').strip()
        if not username:
            return JsonResponse({'status': 'error', 'message': '用户名不能为空'}, status=400)
        if username != user.username and User.objects.filter(username=username).exists():
            return JsonResponse({'status': 'error', 'message': '用户名已存在'}, status=409)
        if email:
            try:
                validate_email(email)
            except ValidationError:
                return JsonResponse({'status': 'error', 'message': '邮箱格式不正确'}, status=400)
        if phone:
            if not phone.isdigit() or len(phone) != 11:
                return JsonResponse({'status': 'error', 'message': '请输入11位手机号码'}, status=400)
        if role not in ('super_admin', 'admin', 'user'):
            role = user.role
        user.username = username
        user.email = email or None
        user.phone = phone or None
        user.role = role
        if is_active is not None:
            user.is_active = bool(is_active)
        if password:
            user.set_password(password)
        user.save()
        return JsonResponse({'status': 'success', 'message': '编辑成功'})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'编辑失败: {str(e)}'}, status=500)

@login_required
@require_POST
def users_delete(request, user_id: int):
    """删除用户"""
    try:
        if not (request.user.is_staff or request.user.role in ('super_admin', 'admin')):
            return JsonResponse({'status': 'error', 'message': '无权限'}, status=403)
        if user_id == request.user.id:
            return JsonResponse({'status': 'error', 'message': '不能删除当前登录用户'}, status=400)
        user = User.objects.filter(pk=user_id).first()
        if not user:
            return JsonResponse({'status': 'error', 'message': '用户不存在'}, status=404)
        if user.role == 'super_admin':
            return JsonResponse({'status': 'error', 'message': '不能删除超级管理员'}, status=403)
        user.delete()
        return JsonResponse({'status': 'success', 'message': '删除成功'})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': f'删除失败: {str(e)}'}, status=500)